Commit 4ea0f6b9 authored by Bill Hoffman's avatar Bill Hoffman
Browse files

ENH: add enable language support for PROJECT command, this means that a C only...

ENH: add enable language support for PROJECT command, this means that a C only project can be built with cmake, even without a cxx compiler
parent 81ebecae
This diff is collapsed.
......@@ -6,7 +6,7 @@ LINK_DIRECTORIES(${HELLO_BINARY_DIR}/Hello)
# Add executable called "helloDemo" that is built from the source files
# "demo.cxx" and "demo_b.cxx". The extensions are automatically found.
ADD_EXECUTABLE(helloDemo demo demo_b)
ADD_EXECUTABLE(helloDemo demo.cxx demo_b.cxx)
# Link the executable to the Hello library.
TARGET_LINK_LIBRARIES(helloDemo Hello)
# Create a library called "Hello" which includes the source file "hello.cxx".
# The extension is already found. Any number of sources could be listed here.
ADD_LIBRARY(Hello hello)
ADD_LIBRARY(Hello hello.cxx)
SOURCE_FILES(SRCS
SET(SRCS
cmake.cxx
cmakewizard.cxx
cmMakeDepend.cxx
......@@ -37,13 +37,15 @@ cmListFileCache.h
CONFIGURE_FILE(
${CMake_SOURCE_DIR}/Source/cmConfigure.cmake.h.in
${CMake_BINARY_DIR}/Source/cmConfigure.h )
# add the include path to find the .h
INCLUDE_DIRECTORIES(${CMake_BINARY_DIR}/Source)
# let cmake know it is supposed to use it
ADD_DEFINITIONS(-DCMAKE_BUILD_WITH_CMAKE)
IF (WIN32)
SOURCE_FILES(SRCS
SET(SRCS ${SRCS}
cmDSWWriter.cxx
cmDSPWriter.cxx
cmMSProjectGenerator.cxx
......@@ -73,17 +75,17 @@ IF (UNIX)
ENDIF (CURSES_LIBRARY)
ENDIF (UNIX)
SOURCE_FILES(SRCS cmUnixMakefileGenerator.cxx cmUnixMakefileGenerator.h)
SET(SRCS ${SRCS} cmUnixMakefileGenerator.cxx cmUnixMakefileGenerator.h)
# create a library used by the command line and the GUI
ADD_LIBRARY(CMakeLib SRCS)
ADD_LIBRARY(CMakeLib ${SRCS})
# always link in the library
LINK_LIBRARIES(CMakeLib)
# the library is found here
LINK_DIRECTORIES(${CMake_BINARY_DIR}/Source)
ADD_EXECUTABLE(cmake cmakemain)
ADD_EXECUTABLE(cmake cmakemain.cxx)
ADD_EXECUTABLE(DumpDocumentation cmDumpDocumentation)
ADD_EXECUTABLE(ctest ctest.cxx cmSystemTools.cxx cmRegularExpression.cxx)
......@@ -106,6 +108,11 @@ IF(BUILD_TESTING)
${CMake_BINARY_DIR}/Tests/Simple
simple)
ADD_TEST(conly ${CMake_BINARY_DIR}/Source/cmaketest
${CMake_SOURCE_DIR}/Tests/COnly
${CMake_BINARY_DIR}/Tests/COnly
conly)
ADD_TEST(complex ${CMake_BINARY_DIR}/Source/cmaketest
${CMake_SOURCE_DIR}/Tests/Complex
${CMake_BINARY_DIR}/Tests/Complex
......
......@@ -36,7 +36,7 @@ cmBorlandMakefileGenerator::~cmBorlandMakefileGenerator()
}
void cmBorlandMakefileGenerator::ComputeSystemInfo()
void cmBorlandMakefileGenerator::EnableLanguage(const char*)
{
// now load the settings
if(!m_Makefile->GetDefinition("CMAKE_ROOT"))
......@@ -53,11 +53,15 @@ void cmBorlandMakefileGenerator::ComputeSystemInfo()
message += outdir;
cmSystemTools::Error(message.c_str());
}
if(!this->GetLanguageEnabled("CXX"))
{
std::string fpath =
m_Makefile->GetDefinition("CMAKE_ROOT");
fpath += "/Templates/CMakeBorlandWindowsSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
this->SetLanguageEnabled("CXX");
}
std::string fpath =
m_Makefile->GetDefinition("CMAKE_ROOT");
fpath += "/Templates/CMakeBorlandWindowsSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
}
......
......@@ -41,7 +41,7 @@ public:
{ return new cmBorlandMakefileGenerator;}
///! figure out about the current system information
virtual void ComputeSystemInfo();
virtual void EnableLanguage(const char*);
protected:
virtual void OutputMakeVariables(std::ostream&);
......
......@@ -121,20 +121,9 @@ void cmDSWWriter::WriteDSWFile(std::ostream& fout)
k != allListFiles.end(); ++k)
{
cmMakefile* mf = *k;
cmMSProjectGenerator* pg = 0;
// if not this makefile, then create a new generator
if(m_Makefile != mf)
{
// Create an MS generator with DSW off, so it only creates dsp files
pg = new cmMSProjectGenerator;
}
else
{
pg = (cmMSProjectGenerator*)m_Makefile->GetMakefileGenerator();
}
cmMSProjectGenerator* pg = (cmMSProjectGenerator*)mf->GetMakefileGenerator();
// make sure the generator is building dsp files
pg->BuildDSWOff();
mf->SetMakefileGenerator(pg);
mf->GenerateMakefile();
// Get the source directory from the makefile
std::string dir = mf->GetStartDirectory();
......
......@@ -88,7 +88,7 @@ void cmMSDotNETGenerator::SetLocal(bool local)
m_BuildSLN = !local;
}
void cmMSDotNETGenerator::ComputeSystemInfo()
void cmMSDotNETGenerator::EnableLanguage(const char*)
{
// now load the settings
if(!m_Makefile->GetDefinition("CMAKE_ROOT"))
......@@ -97,10 +97,14 @@ void cmMSDotNETGenerator::ComputeSystemInfo()
"CMAKE_ROOT has not been defined, bad GUI or driver program");
return;
}
std::string fpath =
m_Makefile->GetDefinition("CMAKE_ROOT");
fpath += "/Templates/CMakeDotNetSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
if(!this->GetLanguageEnabled("CXX"))
{
std::string fpath =
m_Makefile->GetDefinition("CMAKE_ROOT");
fpath += "/Templates/CMakeDotNetSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
this->SetLanguageEnabled("CXX");
}
}
......@@ -187,20 +191,10 @@ void cmMSDotNETGenerator::WriteSLNFile(std::ostream& fout)
k != allListFiles.end(); ++k)
{
cmMakefile* mf = *k;
cmMSDotNETGenerator* pg = 0;
// if not this makefile, then create a new generator
if(m_Makefile != mf)
{
// Create an MS generator with SLN off, so it only creates dsp files
pg = new cmMSDotNETGenerator;
}
else
{
pg = static_cast<cmMSDotNETGenerator*>(m_Makefile->GetMakefileGenerator());
}
cmMSDotNETGenerator* pg =
static_cast<cmMSDotNETGenerator*>(mf->GetMakefileGenerator());
// make sure the generator is building dsp files
pg->BuildSLNOff();
mf->SetMakefileGenerator(pg);
mf->GenerateMakefile();
// Get the source directory from the makefile
std::string dir = mf->GetStartDirectory();
......
......@@ -64,7 +64,7 @@ public:
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
*/
virtual void ComputeSystemInfo();
virtual void EnableLanguage(const char*);
protected:
/**
......
......@@ -55,7 +55,7 @@ void cmMSProjectGenerator::SetLocal(bool local)
m_BuildDSW = !local;
}
void cmMSProjectGenerator::ComputeSystemInfo()
void cmMSProjectGenerator::EnableLanguage(const char*)
{
// now load the settings
if(!m_Makefile->GetDefinition("CMAKE_ROOT"))
......
......@@ -73,7 +73,7 @@ public:
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
*/
virtual void ComputeSystemInfo();
virtual void EnableLanguage(const char*);
private:
cmDSWWriter* m_DSWWriter;
......
......@@ -431,23 +431,18 @@ void cmMakefile::AddSource(cmSourceFile& cmfile, const char *srclist)
m_Sources[srclist].push_back(this->AddSource(cmfile));
}
struct FindSrcByName : std::binary_function<cmSourceFile*, cmSourceFile*, bool>
{
public:
bool operator () (const cmSourceFile *f, const cmSourceFile *test) const
{
return (f->GetSourceName() == test->GetSourceName());
}
};
void cmMakefile::RemoveSource(cmSourceFile& cmfile,const char *srclist)
void cmMakefile::RemoveSource(cmSourceFile& cmfile, const char *srclist)
{
std::vector<cmSourceFile*> &maplist = m_Sources[srclist];
std::vector<cmSourceFile*>::iterator f =
std::find_if(maplist.begin(), maplist.end(), std::bind2nd(FindSrcByName(),&cmfile));
if (f!=maplist.end())
for( std::vector<cmSourceFile*>::iterator f = maplist.begin();
f != maplist.end(); ++f)
{
if((*f)->GetSourceName() == cmfile.GetSourceName())
{
maplist.erase(f);
return;
}
}
}
......@@ -1079,8 +1074,7 @@ void cmMakefile::RemoveVariablesInString(std::string& source,
// This is done by reading the sub directory CMakeLists.txt files,
// then calling this function with the new cmMakefile object
void
cmMakefile::FindSubDirectoryCMakeListsFiles(std::vector<cmMakefile*>&
makefiles)
cmMakefile::FindSubDirectoryCMakeListsFiles(std::vector<cmMakefile*>& makefiles)
{
// loop over all the sub directories of this makefile
const std::vector<std::string>& subdirs = this->GetSubDirectories();
......@@ -1102,6 +1096,7 @@ cmMakefile::FindSubDirectoryCMakeListsFiles(std::vector<cmMakefile*>&
else
{
cmMakefile* mf = new cmMakefile;
mf->SetMakefileGenerator(m_MakefileGenerator->CreateObject());
makefiles.push_back(mf);
// initialize new makefile
mf->SetHomeOutputDirectory(this->GetHomeOutputDirectory());
......@@ -1322,3 +1317,7 @@ cmSourceFile* cmMakefile::AddSource(cmSourceFile const&sf)
}
void cmMakefile::EnableLanguage(const char* lang)
{
m_MakefileGenerator->EnableLanguage(lang);
}
......@@ -501,7 +501,9 @@ public:
/** Recursivly read and create a cmMakefile object for
* all CMakeLists.txt files in the GetSubDirectories list.
* Once the file is found, it ReadListFile is called on
* the cmMakefile created for it.
* the cmMakefile created for it. CreateObject is called on
* the prototype to create a cmMakefileGenerator for each cmMakefile that
* is created.
*/
void FindSubDirectoryCMakeListsFiles(std::vector<cmMakefile*>& makefiles);
......@@ -523,6 +525,9 @@ public:
/** Check if a command exists. */
bool CommandExists(const char* name) const;
///! Enable support for the named language, if null then all languages are enabled.
void EnableLanguage(const char* );
protected:
std::string m_Prefix;
std::vector<std::string> m_AuxSourceDirectories; //
......
......@@ -19,6 +19,7 @@
// static list of registered generators
std::map<cmStdString, cmMakefileGenerator*>
cmMakefileGenerator::s_RegisteredGenerators;
std::map<cmStdString, bool> cmMakefileGenerator::s_LanguageEnabled;
void cmMakefileGenerator::SetMakefile(cmMakefile* mf)
......@@ -77,3 +78,25 @@ cmMakefileGenerator::CreateGenerator(const char* name)
}
return 0;
}
void cmMakefileGenerator::SetLanguageEnabled(const char* l)
{
s_LanguageEnabled[l] = true;
}
bool cmMakefileGenerator::GetLanguageEnabled(const char* l)
{
return (s_LanguageEnabled.count(l) > 0);
}
void cmMakefileGenerator::ClearEnabledLanguages()
{
s_LanguageEnabled.clear();
}
......@@ -69,11 +69,19 @@ public:
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
*/
virtual void ComputeSystemInfo() = 0;
virtual void EnableLanguage(const char*) = 0;
virtual ~cmMakefileGenerator(){};
/**
* Set/Get and Clear the enabled languages.
*/
static void SetLanguageEnabled(const char*);
static bool GetLanguageEnabled(const char*);
static void ClearEnabledLanguages();
protected:
static std::map<cmStdString, cmMakefileGenerator*> s_RegisteredGenerators;
static std::map<cmStdString, bool> s_LanguageEnabled;
cmMakefile* m_Makefile;
};
......
......@@ -97,7 +97,7 @@ std::string cmNMakeMakefileGenerator::ShortPathCommand(const char* command)
}
void cmNMakeMakefileGenerator::ComputeSystemInfo()
void cmNMakeMakefileGenerator::EnableLanguage(const char*)
{
// now load the settings
if(!m_Makefile->GetDefinition("CMAKE_ROOT"))
......@@ -106,10 +106,14 @@ void cmNMakeMakefileGenerator::ComputeSystemInfo()
"CMAKE_ROOT has not been defined, bad GUI or driver program");
return;
}
std::string fpath =
m_Makefile->GetDefinition("CMAKE_ROOT");
fpath += "/Templates/CMakeNMakeWindowsSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
if(!this->GetLanguageEnabled("CXX"))
{
std::string fpath =
m_Makefile->GetDefinition("CMAKE_ROOT");
fpath += "/Templates/CMakeNMakeWindowsSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
this->SetLanguageEnabled("CXX");
}
}
......
......@@ -41,7 +41,7 @@ public:
{ return new cmNMakeMakefileGenerator;}
///! figure out about the current system information
virtual void ComputeSystemInfo();
virtual void EnableLanguage(const char*);
protected:
std::string ShortPath(const char* path);
std::string ShortPathCommand(const char* command);
......
......@@ -19,7 +19,7 @@
// cmProjectCommand
bool cmProjectCommand::InitialPass(std::vector<std::string> const& args)
{
if(args.size() != 1 )
if(args.size() < 1 )
{
this->SetError("PROJECT called with incorrect number of arguments");
return false;
......@@ -48,6 +48,17 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args)
m_Makefile->AddDefinition("PROJECT_NAME", args[0].c_str());
if(args.size() > 1)
{
for(size_t i =1; i < args.size(); ++i)
{
m_Makefile->EnableLanguage(args[i].c_str());
}
}
else
{
m_Makefile->EnableLanguage(0);
}
return true;
}
......@@ -73,7 +73,12 @@ public:
virtual const char* GetFullDocumentation()
{
return
"PROJECT(projectname) Sets the name of the Microsoft workspace .dsw file. Does nothing on UNIX currently\n";
"PROJECT(projectname [C++ C Java])\n"
"Sets the name of the project. "
"This creates the variables projectname_BINARY_DIR and projectname_SOURCE_DIR. "
"Optionally you can specify which languages your project supports. "
"By default all languages are supported. If you do not have a C++ compiler, but want"
" to build a c program with cmake, then use this option.";
}
cmTypeMacro(cmProjectCommand, cmCommand);
......
......@@ -49,7 +49,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args)
if(args[1] != "CACHE" && args[2] != "CACHE")
{
value = args[1];
for(unsigned int i =2; i < args.size(); ++i)
for(size_t i =2; i < args.size(); ++i)
{
value += ";";
value += args[i];
......
......@@ -53,7 +53,7 @@ public:
virtual const char* GetFullDocumentation()
{
return
"SET_SOURCE_FILES_PROPERTIES(flags file1 file2 [ABSTRACT|WRAP_EXCLUDE|GENERATED|COMPILE_FLAGS] [flags]) "
"SET_SOURCE_FILES_PROPERTIES(file1 file2 .. filen [ABSTRACT|WRAP_EXCLUDE|GENERATED|COMPILE_FLAGS] [flags]) "
"Set properties on a file. The syntax for the command is to list all the files you want "
"to change, and then provide the values you want to set next.";
}
......
......@@ -75,3 +75,15 @@ void cmTarget::MergeLibraries(const LinkLibraries &ll)
}
bool cmTarget::HasCxx() const
{
for(std::vector<cmSourceFile*>::const_iterator i = m_SourceFiles.begin();
i != m_SourceFiles.end(); ++i)
{
if((*i)->GetSourceExtension() != "c")
{
return true;
}
}
return false;
}
......@@ -71,6 +71,8 @@ public:
{return m_SourceFiles;}
std::vector<cmSourceFile*> &GetSourceFiles() {return m_SourceFiles;}
///! does this target have a cxx file in it
bool HasCxx() const;
/**
* Get the list of the source files used by this target
*/
......
......@@ -604,8 +604,17 @@ void cmUnixMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout,
std::string command = "$(RM) lib";
command += name;
command += "$(SHLIB_SUFFIX)";
std::string command2 = "$(CMAKE_CXX_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) "
"$(CMAKE_SHLIB_BUILD_FLAGS) $(CMAKE_CXX_FLAGS) -o \\\n";
std::string command2;
if(t.HasCxx())
{
command2 = "$(CMAKE_CXX_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) "
"$(CMAKE_SHLIB_BUILD_FLAGS) $(CMAKE_CXX_FLAGS) -o \\\n";
}
else
{
command2 = "$(CMAKE_C_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) "
"$(CMAKE_SHLIB_BUILD_FLAGS) $(CMAKE_C_FLAGS) -o \\\n";
}
command2 += "\t ";
std::string libName = m_LibraryOutputPath + "lib" + std::string(name) + "$(SHLIB_SUFFIX)";
libName = this->ConvertToOutputPath(libName.c_str());
......@@ -639,8 +648,17 @@ void cmUnixMakefileGenerator::OutputModuleLibraryRule(std::ostream& fout,
depend += this->CreateMakeVariable(name, "_SRC_OBJS")
+ ") $(" + this->CreateMakeVariable(name, "_DEPEND_LIBS") + ")";
std::string command = "$(RM) lib" + std::string(name) + "$(MODULE_SUFFIX)";
std::string command2 = "$(CMAKE_CXX_COMPILER) $(CMAKE_MODULE_LINK_FLAGS) "
"$(CMAKE_MODULE_BUILD_FLAGS) $(CMAKE_CXX_FLAGS) -o \\\n";
std::string command2;
if(t.HasCxx())
{
command2 = "$(CMAKE_CXX_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) "
"$(CMAKE_SHLIB_BUILD_FLAGS) $(CMAKE_CXX_FLAGS) -o \\\n";
}
else
{
command2 = "$(CMAKE_C_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) "
"$(CMAKE_SHLIB_BUILD_FLAGS) $(CMAKE_C_FLAGS) -o \\\n";
}
command2 += "\t ";
std::string libName = m_LibraryOutputPath + "lib" + std::string(name) + "$(MODULE_SUFFIX)";
libName = this->ConvertToOutputPath(libName.c_str());
......@@ -705,8 +723,17 @@ void cmUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
std::string depend = "$(";
depend += this->CreateMakeVariable(name, "_SRC_OBJS")
+ ") $(" + this->CreateMakeVariable(name, "_DEPEND_LIBS") + ")";
std::string command =
"$(CMAKE_CXX_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) $(CMAKE_CXX_FLAGS) ";
std::string command;
if(t.HasCxx())
{
command =
"$(CMAKE_CXX_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) $(CMAKE_CXX_FLAGS) ";
}
else
{
command =
"$(CMAKE_C_COMPILER) $(CMAKE_SHLIB_LINK_FLAGS) $(CMAKE_C_FLAGS) ";
}
command += "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") ";
std::strstream linklibs;
this->OutputLinkLibraries(linklibs, 0, t);
......@@ -1451,10 +1478,9 @@ void cmUnixMakefileGenerator::RecursiveGenerateCacheOnly()
mf->AddDefinition("RUN_CONFIGURE", true);
}
cmUnixMakefileGenerator* gen =
static_cast<cmUnixMakefileGenerator*>(this->CreateObject());
static_cast<cmUnixMakefileGenerator*>(mf->GetMakefileGenerator());
gen->SetCacheOnlyOn();
gen->SetRecurseOff();
mf->SetMakefileGenerator(gen);
mf->GenerateMakefile();
}
// CLEAN up the makefiles created
......@@ -1470,7 +1496,6 @@ void cmUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout)
"# the standard shell for make\n"
"SHELL = /bin/sh\n"
"\n"
"CMAKE_LIB_EXT = @CMAKE_LIB_EXT@\n"
"CMAKE_RANLIB = @CMAKE_RANLIB@\n"
"CMAKE_AR = @CMAKE_AR@\n"
"CMAKE_AR_ARGS = @CMAKE_AR_ARGS@\n"
......@@ -2034,7 +2059,7 @@ void cmUnixMakefileGenerator::SetLocal (bool local)
}
}
void cmUnixMakefileGenerator::ComputeSystemInfo()
void cmUnixMakefileGenerator::EnableLanguage(const char* lang)
{
if (m_CacheOnly)
{
......@@ -2057,21 +2082,38 @@ void cmUnixMakefileGenerator::ComputeSystemInfo()
envCC[4999] = 0;
putenv(envCC);
}
// currently we run configure shell script here to determine the info
std::string output;
std::string cmd = "cd ";
cmd += this->ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory());
cmd += "; ";
const char* root
= m_Makefile->GetDefinition("CMAKE_ROOT");
cmd += root;
cmd += "/Templates/configure";
cmSystemTools::RunCommand(cmd.c_str(), output);
std::string root
= this->ConvertToOutputPath(m_Makefile->GetDefinition("CMAKE_ROOT"));
// if no lang specified use CXX
if(!lang )
{
lang = "CXX";
}
// if CXX or C, then enable C
if((!this->GetLanguageEnabled(lang) && lang[0] == 'C'))
{
std::string cmd = root;
cmd += "/Templates/cconfigure";
cmSystemTools::RunCommand(cmd.c_str(), output,
this->ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory()).c_str());
std::string fpath = m_Makefile->GetHomeOutputDirectory();
fpath += "/CCMakeSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
this->SetLanguageEnabled("C");
}
// if CXX
if(!this->GetLanguageEnabled(lang) || strcmp(lang, "CXX") == 0)
{
std::string cmd = root;
cmd += "/Templates/cxxconfigure";
cmSystemTools::RunCommand(cmd.c_str(), output,
this->ConvertToOutputPath(m_Makefile->GetHomeOutputDirectory()).c_str());
std::string fpath = m_Makefile->GetHomeOutputDirectory();
fpath += "/CXXCMakeSystemConfig.cmake";
m_Makefile->ReadListFile(NULL,fpath.c_str());
this->SetLanguageEnabled("CXX");
}
m_Makefile->AddDefinition("RUN_CONFIGURE", true);