Why doesn't g++ find the precompiled-header that's in the -I include-path? - g++

I'm trying to build a precompiled header and an executable, like so:
g++ -g -Wall -std=c++17 \
-c ./src/pch.hpp -o ./build/pch.hpp.gch
g++ -g -Wall -std=c++17 \
-c ./src/*.cpp \
-I./build/ -include pch.hpp
The pch.hpp.gch file is created correctly. But for each of the .cpp files, I'm getting the following error:
1 error generated.
<built-in>:1:10: fatal error: 'pch.hpp' file not found
#include "pch.hpp"
I think my compilation line is correct, based on the gcc Precompiled Headers documentation:
-I./build/ tells it to add build directory to the include search-path.
-include pch.hpp prepends an #include <pch.hpp> directive to each file.
The compiler searches for precompiled headers, with the .gch suffix, for each of its #include directives.
Why is my compilation line not working as expected?
There are some things I've tried which do give me better results, but they don't look correct to me.
If I modify the include to search for a .gch file, then the file is found, in line with what I'd expect. That is, -include pch.hpp.gch, instead of -include pch.hpp .
But then, the PCH is interpreted as a binary file, and compilation fails:
g++ -g -Wall -std=c++17 \
-c ./src/*.cpp \
-I./build/ -include pch.hpp.gch
./build/pch.hpp.gch:2:22: error: source file is not valid UTF-8
I'm not surprised that #include <pch.hpp.gch> doesn't compile. But I'm mentioning this since it seems to show that in my original command, the build folder is searched (as I expected), but the mechanism that knows to use the .gch file instead of a regular header isn't active. Weird.
Alternatively, if I add the src folder to the header search path, it works:
g++ -g -Wall -std=c++17 \
-c ./src/*.cpp \
-I./src/ -I./build/ -include pch.hpp
I do not understand why adding another, irrelevant include-path solves anything. Weird.
My current working solution is to drop the -I include-path directive entirely, and specify a more complete path to build/pch.hpp:
g++ -g -Wall -std=c++17 \
-c ./src/*.cpp \
-include ./build/pch.hpp
This one works as expected. I'm not sure why it's necessary, though, and it's peculiar and inconvenient.
Is this how a PCH is supposed to be used? Why does my original line not work, and what am I meant to be doing instead?

From the documentation:
A precompiled header file is searched for when #include is seen in the compilation. As it searches for the included file (see Search Path in The C Preprocessor) the compiler looks for a precompiled header in each directory just before it looks for the include file in that directory. The name searched for is the name specified in the #include with ‘.gch’ appended. If the precompiled header file cannot be used, it is ignored.
For instance, if you have #include "all.h", and you have all.h.gch in the same directory as all.h, then the precompiled header file is used if possible, and the original header is used otherwise.
It means that the compiler must be able to find BOTH h-file and gch-file while building cpp. So they BOTH should in the same directory or the same include search path.

Related

error: target Objective-C runtime differs in PCH file vs. current file

I'm trying to compile Objective-C or .m file using command-line (generated by CMake) for Catalyst, but am stuck with two compile errors!
1. Whenever I enable Catalyst with one of below flags:
-target x86_64-apple-ios-macabi
-target x86_64-apple-ios13.0-macabi
-target x86_64-apple-ios13.5-macabi
-target x86_64-apple-ios13.7-macabi
2. Then force rebuild (click Clean Build Folder, then Build).
3. The build fails with error:
fatal error: 'UIKit/UIKit.h' file not found
4. But once I switch to 13.6, I mean, change the flag to:
-target x86_64-apple-ios13.6-macabi
5. Then force-rebuild, I get a new error:
error: target Objective-C runtime differs in PCH file vs. current file
Note that I am not using any PCH file, and both errors seem completely confusing.
Also, I searched and found post similar to second error, but the fix suggested (namely, switching to 13.6) is the cause of the second error.
(Was supposed to fix it, yet is triggering it).
After capturing Xcode's full command-line, I noticed that it had -x objective-c flag while my CMake had not!
After searching (about how CMake support's Obj-C),
found actual mistake!
1. Basically, CMake needed me to do something like:
project(MyProject C CXX OBJC OBJCXX)
Instead of:
project(MyProject)
2. Also, should add Obj-C flags into CMAKE_OBJC_FLAGS instead of CMAKE_C_LINK_FLAGS variable.
3. Now CMake automaticaly adds missing -x objective-c flag, and I just need to add my custom flags.
Full Xcode command-line:
-x objective-c -target x86_64-apple-ios13.6-macabi -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -fobjc-arc -fmodules -gmodules -fmodules-cache-path=/Users/admin/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fbuild-session-file=/Users/admin/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation -fmodules-validate-once-per-build-session -fmodule-name=MyProject -fapplication-extension -fpascal-strings -O0 -fno-common -DDEBUG=1 -DOBJC_OLD_DISPATCH_PROTOTYPES=0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -fasm-blocks -fstrict-aliasing -g -fprofile-instr-generate -fcoverage-mapping -index-store-path /MyBuildDir/Index/DataStore -iquote /MyBuildDir-cofig/MyProject-generated-files.hmap -I/MyBuildDir-cofig/MyProject-own-target-headers.hmap -I/MyBuildDir-cofig/MyProject-all-non-framework-target-headers.hmap -ivfsoverlay /MyBuildDir-cofig/all-product-headers.yaml -iquote /MyBuildDir-cofig/MyProject-project-headers.hmap -I/MyProductDir/include -isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/iOSSupport/usr/include -I/MyBuildDir-cofig/DerivedSources-normal/x86_64 -I/MyBuildDir-cofig/DerivedSources/x86_64 -I/MyBuildDir-cofig/DerivedSources -F/MyProductDir -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/iOSSupport/System/Library/Frameworks -MMD -MT dependencies -MF /MyBuildDir-cofig/Objects-normal/x86_64/my-source.d --serialize-diagnostics /MyBuildDir-cofig/Objects-normal/x86_64/my-source.dia -c /Users/admin/my-project/my-source.m -o /MyBuildDir-cofig/Objects-normal/x86_64/my-source.o
Note that I replaced paths to shorten above, like:
MyBuildDir => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr
MyBuildDir-config => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr/Build/Intermediates.noindex/MyProject.build/Debug-maccatalyst/MyProject.build/
MyProductDir => /Users/admin/Library/Developer/Xcode/DerivedData/MyProject-gczfeuobxydqjrfbdhwzpqjsseyr/Build/Products/Debug-maccatalyst

How did Cygwin g++ resolve it?

I am puzzled how a mere g++ -o testpoco testpoco.cpp -lPocoFoundation was able to compile successfully in my Cygwin environment. The complete C++ code is below:
#include <Poco/File.h>
int main (int argc, char *argv[])
{
Poco::File f("/tmp/test.log");
if (f.exists()) {
return 1;
}
return 0;
}
I installed the cygwin Poco development headers and libraries and I verified they are in:
/usr/include/Poco/ (the header files)
/usr/lib/ (the libraries)
But without specifying those include and library path in g++ how did it was able to compile and produce the exe? I checked the output of g++ -v and did not see any routes to Poco.
The compiler has default search paths for include files and for libraries. (Actually the latter applies to the linker, not the compiler, but the g++ command invokes both.)
/usr/include and /usr/lib are in those default search paths.
You specified #include <Poco/File.h>, so the compiler found /usr/include/Poco/File.h.
You specified -lPocoFoundation, so the linker found /usr/lib/libPocoFoundation.dll.a, the file that contains the code implementing the PocoFoundation library under Cygwin.
I checked the output of g++ -v and did not see any routes to Poco
The command g++ -v will just print out some version information about GCC, and how it was configured. Adding the -v option to your real commands used for compiling and/or linking will show the search paths for headers and libraries.
In other words, instead of just g++ -v you should try:
g++ -o testpoco testpoco.cpp -lPocoFoundation -v
This will show the search paths that Keith Thompson refers to in his answer.

cmake finds package, but does not add to include path

I am trying to compile (on FreeBSD, if that matters) a program that uses cmake. The CMakeLists.txt contains the lines
find_package(GLUT REQUIRED)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${OPENGL32_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS})
and cmake does not report any errors, but when I run make afterwards, I get
[…]
/usr/bin/c++ -fopenmp -I/path/build -o CMakeFiles/scriptbots.dir/GLView.cpp.o -c /path/GLView.cpp
[…]
In file included from /path/GLView.cpp:2:
/path/GLView.cpp:10:21: error: GL/glut.h: No such file or directory
[…]
GL/glut.h exists in /usr/local/include, which is not given as -I argument to /usr/bin/c++.
Compiling works when I explicitly add -I/usr/local/include to CMakeFiles/scriptbots.dir/flags.make. What do I need to change to make the project compile without manually changing the flags file?
As per its documentation, FindGLUT sets variable GLUT_INCLUDE_DIR, not GLUT_INCLUDE_DIRS. Change this in your CMakeList and it should work.

Unable to compile sharable .o files with g++

When i compile with the following command:
g++ -fPIC -o obj/buffer.o buffer.cpp
I get the following error:
/usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../x86_64-linux-gnu/crt1.o:
In function _start': (.text+0x20): undefined reference tomain'
I am thought with the -fPIC flag, I didn't need a main function. I get this error with all of the cpp files. I do have a main.cpp that has the shared library functions in it. You can get the source code at the following:
git clone https://github.com/nterry/39DLL-4-Linux.git
Any ideas? I know that I can use the ld binary to put all of the o files in the an so once they're done, I just need help in building them all into shareable .o files
I think that I answered my question. I added a -c to the command and it seems to have worked. Here is the command I used:
g++ -fPIC -c -o obj/list.o list.cpp
That is one of several cpp files, and all seemed to work.

C++ linking issue: multiple definition

Unfortunately I cannot post all of the source code here. I can describe the structure though. All header files have #ifndef/#define/#endif guards. The structure is as follows:
node.h - included by tree.h
tree.h - included by tree.cpp and main.cpp
tree.cpp
main.cpp
In node.h in the global namespace, I declare the following free standing function:
bool char_sort_func(Path first, Path second)
{
return (first->label() < second->label());
}
(Note: as shown bellow, a Path is just a shared_ptr) When I try to build, I get a multiple definition error saying that the function is present in both tree.o and main.o:
> make
g++ -c -g -Wall main.cpp -I /usr/include
g++ -c -g -Wall tree.cpp -I /usr/include
g++ -Wall -o tool tree.o main.o -L /usr/lib -l boost_program_options
main.o: In function `char_sort_func(boost::shared_ptr<Edge>, boost::shared_ptr<Edge>)':
node.h:70: multiple definition of `char_sort_func(boost::shared_ptr<Edge>, boost::shared_ptr<Edge>)'
tree.o:node.h:70: first defined here
collect2: ld returned 1 exit status
make: *** [all] Error 1
I tried searching all of the source files to see if that was true, however, I don't see it in any wrong places:
> grep char_sort_func *
Binary file main.o matches
node.h:bool char_sort_func(Path first, Path second)
node.h: std::sort(edges_.begin(), edges_.end(), char_sort_func);
Binary file trie.o matches
Sure enough though, it is in the binary files. How can I restructure my code to prevent this linking issue?
This will happen if you declare normal functions in a .h file, because they will be generated in every file that #includes it. Perhaps you meant to declare it inline or static?