Skip to content

Conversation

FilipNur
Copy link

Made simple modifications so that project can be compiled wiith Clang and GCC on Windows

}

#if defined(__clang__) || defined(__GNUC__)
// memory size pointed to by buf variable is checked above
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this check?

Copy link
Author

@FilipNur FilipNur Jun 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wolfpld From what I see, on line 3122 in public/client/TracyProfiler.cpp, there is if statement that checks if buf pointer will be able to contain new data and if not, then memory is allocated with size equal to size of data that will be copied.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #889.

Copy link
Author

@FilipNur FilipNur Jun 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the problem is more complex than it seemed. At the moment only way I can think of to handle fail to memcpy that is using standard language features is to use setjmp and longjmp from signal handling function. Below is simple program that shows how it could work

#include <string.h>
#include <stdint.h>
#include <setjmp.h>
#include <signal.h>

jmp_buf jumpBuffer;

void fun(int sig)
{
	std::cout << "Signal " << sig << '\n';
	longjmp(jumpBuffer, 1);
}

int main()
{
	signal(SIGSEGV, fun);

	uint32_t * dst = (uint32_t *)1234;
	uint32_t src = 56;

	if(setjmp(jumpBuffer) == 0)
	{
		memcpy(dst, &src, sizeof(uint32_t));
	}
	else
	{
		std::cout << "Error!\n";
	}

	std::cout << "Hello, World!\n";

	return 0;
}

The only thing is that fun and jumpBuffer would need to be static inside some object or global.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracy already hooks SIGSEGV for other functionality, so that's additional complexity to consider.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am continuiung to work on this and decided to use pipe write read method like one implemented for linux, but I didn't push anything yet as I am trying to make compilation work on GCC and Clang. I just wanted to ask if -flto option enabled by line 47 in config.cmake:

46 if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT EMSCRIPTEN)
47     set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
48 endif()

is absolutely required for compilation of profiler, as when compiling it with GCC and -flto option there is error caused by too many sections:

.../MSYS2/mingw64/x86_64-w64-mingw32/bin/as.exe: CMakeFiles/tracy-profiler.dir/src/profiler/TracyMicroArchitecture.cpp.obj: too many sections (176497)
...\MSYS2\tmp\ccetkwcc.s: Assembler messages:
...\MSYS2\tmp\ccetkwcc.s: Fatal error: can't write 15 bytes to section .gnu.lto_.profile.4c08db2b of CMakeFiles/tracy-profiler.dir/src/profiler/TracyMicroArchitecture.cpp.obj: 'file too big'

I would just add condition check in cmake file to not enable CMAKE_INTERPROCEDURAL_OPTIMIZATION for GNU, but I don't know if -flto is required or not.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, LTO is entirely optional.

Note that LTO works both with gcc and clang on my end (Linux), so this may as well be some limitation specific to mingw gcc.

@FilipNur FilipNur force-pushed the gcc_and_clang_compatible branch from 3a0af08 to e98001c Compare June 8, 2025 16:42
@FilipNur
Copy link
Author

FilipNur commented Jun 8, 2025

@wolfpld, I finished changing source so it compiles with gcc and clang on Windows. I tested it on both compilers, test program that uses Tracy, and Tracy profiler itself compile successfully. The initial problem with safe memcpy is solved using pipes for data transfer similar to linux implementation. I wasn't able to find fix for too many sections that I mentioned before and just disabled CMAKE_INTERPROCEDURAL_OPTIMIZATION when compiling with gcc.

if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT EMSCRIPTEN)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
# Mingw gcc on windows can't handle section count resulting during compilation of profiler/src/profiler/TracyMicroArchitecture.cpp
if(NOT (MINGW OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") AND WIN32 AND NOT ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move WIN32 as first condition for better readability.


#ifdef _MSC_VER
#if defined _MSC_VER || defined __clang__ || defined __GNUC__
// all checked compilers contain _stat64
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes behavior on non-win32 platforms.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix it.

void write_compact_float(const number_float_t n, detail::input_format_t format)
{
#ifdef __GNUC__
#if defined __GNUC__ || defined __clang__
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

% clang -dM -E -x c /dev/null | grep __GNUC__
#define __GNUC__ 4

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just being explicit. I can change it if needed.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to go to each of the upstream projects with this change (that is not really needed)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this would be due to having unified #if conditions. I removed obviously not needed checks for __clang__, only left ones that coexist with version checking of GNU, as I don't know if there can be any differences, just to be sure.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, does that mean that if __GNUC__ version is checked then for sure clang will not be supported for this block of code, or it still can be checked via #if (<GNUC version check>) || defined __clang__? Because if only version check done in this way is not valid then it still should be possible to check if clang is compiler that is used.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang defines a very old version of gcc version macro, which may affect what features are available. This can be problematic in rare circumstances.

Copy link
Author

@FilipNur FilipNur Jun 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But is #if (<GNUC version check>) || defined __clang__ method valid then or not? Or clang version must be checked separately through for example __clang_major__ __clang_minor__ __clang_patchlevel__ macros?

// clang does not have that problem
#include <cmath>
#endif

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed here?

[18:59 wolf@oberon:~/tracy]% git grep std::pow 
profiler/src/profiler/TracyView_Timeline.cpp:            const auto mult = 1 + std::max( 0.0, 0.7 * std::pow( x, 1.6 ) - 0.8 * std::pow( x, 1.4 ) );

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested, and turns out that using cmake from clang toolchain and gcc compiler created errors. So not needed, will remove.

// gcc throws error for not present std::pow function,
// clang does not have that problem
#include <cmath>
#endif
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct solution would be to change std::pow to pow and include math.h (with no platform checks).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checks are made only to not include it where it is not needed. Code uses std::pow so to change the least amount of stuff only header is added.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that solution is wrong and only works due to happenstance.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested, and turns out that using cmake from clang toolchain and gcc compiler created errors. So not needed, will remove.

@@ -1,4 +1,4 @@
/* stb_image - v2.29 - public domain image loader - http://nothings.org/stb
/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't know. I did repulling, maybe something there, will fix it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now i know, in the current repo there are 2 stb_image.h files, test/stb_image.h has 2.28 and profiler/src/stb_image.h has 2.29. When applying changes I just copied one file in place of the other to not do the same changes again. Now I checked that they are different. Will fix.

@FilipNur
Copy link
Author

FilipNur commented Jun 8, 2025

@wolfpld Fixed things you pointed out and some other minor things.

@mcourteaux
Copy link
Contributor

@FilipNur Your PR rewrites the entire TracyProfiler.cpp file. Can you fix that?

@FilipNur
Copy link
Author

@mcourteaux I know and I don't know why. I will push changes when I resolve this issue.

@mcourteaux
Copy link
Contributor

As I can't assess what your PR does due to this issue, make sure it's still relevant after my last PR was merged.

@FilipNur
Copy link
Author

FilipNur commented Jun 22, 2025

@mcourteaux I see that your pull request is also about mingw compatibility so my pull request might be not needed, as I was trying to achieve something similar. But I have one question: in your changes to TracyProfiler.cpp you did

#ifdef _WIN32
+ #  ifdef _MSC_VER
      __try
      {
          memcpy( buf, data, size );
      {
          success = false;
      }
+ #  else
+     memcpy( buf, data, size );
+ #  endif
    #else
    ...

Where the memcpy, that is executed if _MSC_VER is not defined, is not protected against potential segfault. I am just curious why was it merged, because when I proposed just bare memcpy in first request, @wolfpld sent me to #889, whetre issue says about ensuring safe memcpy.

@wolfpld
Copy link
Owner

wolfpld commented Jun 22, 2025

It's an incremental step.

@FilipNur
Copy link
Author

Fixed line endings in public/client/TracyProfiler.cpp and rebased project to latest master branch.

const size_t batchEndIdx = std::min( inputEntryList.size(), startIdx + (size_t)1024 );

printf( "Resolving symbols [%zu-%zu[\n", startIdx, batchEndIdx );
printf( "Resolving symbols [%zu-%zu]\n", startIdx, batchEndIdx );
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are there changes that are already applied on master?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I saw the difference was space vs tab.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It definitely isn't.

@mcourteaux
Copy link
Contributor

mcourteaux commented Jun 23, 2025

@FilipNur You seem to have made a PR that includes a bunch of commits that are already on master. If you struggle with figuring out how to correct things, a very manual trick I have used once or twice, that resolves this very easily, is to generate a git diff --patch master gcc_and_clang_compatible patch file from your changes between master and your work. The patch file will contain all changes between those to commits, regardless of the history that happened between them. Then you make a new branch, forked from master, (let's say it's called my-temp-branch) and you apply the patch file there. Afterwards you can inspect if everything looks fine, and your new branch seems like the changes you want to commit. Make a commit on that new branch. Now go back to your gcc_and_clang_compatible branch, and git reset --hard my-temp-branch. Git will now ignore your messy git commit history, and have one commit on your gcc_and_clang_compatible branch which is just the patch file you applied.

If you mess up any of the steps, there is always git reflog to find your work back.

@FilipNur
Copy link
Author

Thanks @mcourteaux, I cleaned up the code using your method.

@FilipNur
Copy link
Author

FilipNur commented Jul 6, 2025

@wolfpld Could you check it?

@wolfpld
Copy link
Owner

wolfpld commented Jul 6, 2025

You are still changing way too much code for no reason, especially in external libraries, and there are comments you have not addressed properly. What's there to check?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants