Reputation: 303
I am currently using Visual Studio 2012, Eclipse, CodeBlocks, and MinGW to write C++ 11 code.
Question:
I have noticed features in GCC, (deferred, = vs. immediate, :=, expansions/assignments, etc), and Microsoft's nmake that lead me to wonder what the official "makefile" standard was.
Background:
The difficulty, (*cough), is that I am trying to make sure the code compiles in each environment, as well as trying to cross-compile to other targets as well, (Linux/Ubuntu using OpenGL APIs, Windows 7,8, using DirectX, Android NDK).
One of my core issues is that a lot of the toolsets I am using aren't really "open" to supporting cross platform awesomeness.
Visual Studio 2012: No *nix runnable compiler. Using buggy version of Nov. 2012 C++ CTP Compiler for C++11 support.
GCC 4.7.x/4.8x: Limited to MinGW32 and rough versions of MinGW64.
CMake: Very difficult to get configured correctly, but appears to create makefiles that are specific to GNU, Microsoft, etc. Is there some way to configure this to generate "standard" makefiles?
AutoMake/AutoConf: Appear to only generate GNU compatible makefiles
Upvotes: 2
Views: 3154
Reputation: 303
Answer: There is no multi-platform Makefile Standard: Instead, use standard, multi-platform scripting languages, such as PHP, PERL, Python, (SCons), etc, to Compile C++ Projects
Based on everyone else's comments about their not being a unified standard, the need for a more permanent, extensible, cross-platform-aly elegant solution became a lot more important to me, (besides, I loathe making makefiles!).
So, after looking at Perl, JavaScript, PHP, (even Python script), I settled on using PHP to Build C++ Projects.
There are so many reasons I made this particular choice, but the main reasons were: 1. Number of PHP tools 2. Easy integration this into remote build operations via web interfaces. 3. Windows, Linux, BSD, OSX portability. 4. Support for advanced logic, includes, for projects involving many nested folder structures, namespaces, and cross-compilation.
PHP, with its shell scripting support, cross platform availability, etc, is a natural fit.
So, without further ado, here is a small, quick and dirty Proof of Concept I have just made. Obviously it doesn't "do" anything, but it runs/compiles just fine, and how it would work in a real make file is easily seen.
Thanks for all the help!
<?php
// Windows cannot "del /files/*.o /S /Q" because it confuses paths for switches.
// Made my own Variable for Directory Separator for Readability.
$DS = DIRECTORY_SEPARATOR;
// ***********************************************
// **** Compiler Variables
// ***** use PHP: include "Config.php", etc
// ***** to have external variables and functions.
$Compiler = "mingw32-g++.exe";
$DebugFlags = "";
$CompilationFlags = "-std=c++11 -Wall -c -o";
$LinkFlags = "-Wall -o";
$IncludeFlags =
array(
"-I".$DS."Includes",
"-L".$DS."Redist".$DS."Headers"
);
$LibraryLocations =
array(
"-L".$DS."Lib",
"-L".$DS."Redist".$DS."Lib"
);
// ***********************************************
// **** Project Properties
class Project {
public $Name = "";
public $Location = "";
public function __construct($name="Project", $location="")
{
$this->Name = $name;
$this->Location = $location;
}
}
$SubProjects =
array(
new Project("Framework", str_replace("/", $DS, "../Projects/API/Source"))
// new Project("Logging", str_replace("/", $DS, "../Projects/Logging/Projects/API/Source"),
);
// ***********************************************
// **** Environment Variables
$BuildRoot = "D:".$DS."Build".$DS;
$ObjectRoot = $BuildRoot + "OBJs".$DS;
$LibRoot = $BuildRoot + "LIBs".$DS;
$RunRoot = $BuildRoot + "Run".$DS;
$ConfigRoot = getcwd();
$directory = ".".$DS;
$filterList = array(".", "..");
$commandOutput = array("");
$returnValue = 1;
$directoryContents = array_diff(scandir($directory), $filterList);
// ***********************************************
// ***** Main Execution Block
// print_r($SubProjects);
echo PHP_EOL . PHP_EOL;
echo "***********************************************" . PHP_EOL;
echo "***** Building: Starting" . PHP_EOL;
ProcessSubProjects($SubProjects);
echo "***********************************************" . PHP_EOL;
echo "***** Building: Finished" . PHP_EOL;
// ***********************************************
function ProcessSubProjects($subProjects)
{
foreach ($subProjects as $project)
{
$command = 'dir ' . realpath($project->Location);
$commandEcho = array();
// echo $project->Location . PHP_EOL;
// echo realpath($project->Location) . PHP_EOL;
echo PHP_EOL . $command . PHP_EOL . PHP_EOL;
exec ($command, $commandEcho);
foreach ($commandEcho as $message)
{
echo $message . PHP_EOL;
}
}
}
?>
Upvotes: 0
Reputation: 100836
GNU make is an implementation of the POSIX specification for make, which you can find here http://pubs.opengroup.org/onlinepubs/9699919799/ Under "Shell and Utilities", search for "make". However you will quickly discover that the parts of make which are standardized are very anemic and won't let you create very sophisticated make environments. That's why GNU make has so many additional features and capabilities.
Additionally, Windows developers don't care that much about POSIX, and especially not the shell & utilities section of POSIX. So even if you can restrict yourself to that subset it doesn't buy you that much: portability across instances of POSIX which don't already use GNU make, basically (both Linux and MacOS use GNU make by default).
You basically have two choices: you can either get a build tool that will work across multiple platforms (GNU make, for example, can be compiled and used on just about every OS available today, but there are other tools such as scons, cook, bras, etc.), or you can use a "meta-tool" like cmake, which instead of actually building your code it will generate build control files for whatever native build tool you want to use (make, Eclipse, XCode, VisualStudio) then you use that native build tool.
Upvotes: 1
Reputation: 153909
The only standard for makefiles is Posix (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html). This is not followed by Visual Studios, and the MinGW make is actually GNU make, which has an option to be Posix compatible, but has a very large number of extensions. (I'm not sure about Eclipse and CodeBlocks, but they probably use GNU make as well.)
The makefile you use is largely independent of the compiler. The Posix standard make is a minimum make; I would recommend using GNU make everywhere, mainly because it is portable, and it is the most powerful in terms of features. On the other hand, it's not easy to learn (and none of the makes I know are particularly readable). Still, I've used the same GNU makefiles under Solaris (with Sun CC and g++), Linux (with g++) and Windows (with MSVC and g++).
With regards to running C++ from the makefile, I also do this all the time, as well as running Python and shell scripts. There are two ways to do this:
machineGenerated.cpp : somethingElse myPreProcessor myPreProcessor somethingElse > machineGenerated.cppYou can also have rules to build `myPreProcessor` in the makefile.
One thing I've found useful when supporting multiple platforms:
dependsPath := $(strip $(arch))-$(strip $(syst))-$(strip $(comp))
configPath := conf/$(dependsPath)
include $(makefilesDir)/$(configPath)/system.mk
Normally, I'll set shell variables for my default arch, syst and
comp (compiler), but I can override them on the command line,
and so compile with both g++ and VC++ on the same machine (or
i686
and x86-64
).
Upvotes: 4
Reputation: 101456
There is no C++ Standard for make systems. This is purely implementation defined stuff.
For cross-platform work (being both cross-operating system and cross-toolchain), I have found the most popular choice being CMake. I'm not a fan of CMake's syntax or various complexities, and I don't enjoy working with it -- but it does work, and it seems like everybody uses it. CMake skills you gain working on one project will transfer to many others.
Yes, you can get "standard" makefiles out of CMake. This is a function of the generator:
cmake -G "Unix Makefiles" ...
Will generate makefiles compatible with *nix make
.
Upvotes: 7