How I Fixed: Clang/ld libssl (-lssl) not found error while installing psycopg2 on Mac OS (Apple Silicon/arm64)

If you’re like me and you use Homebrew to install everything, you might have run into this error while doing pip3 install psycopg2

Psycopg2 requires libpq and pg_config along with OpenSSL to install. While I could have also just installed it with psycopg2-binary, I wanted to find out what was causing this issue.

I had libpq installed by Homebrew in /opt/homebrew/Cellar/libpq/16.1_1/ and OpenSSL in /opt/homebrew/Cellar/openssl@3/3.2.1/

While installing psycopg2, you have to have pg_config in your path. The setup.py in the source even provides a dedicated option for that. I was passing /opt/homebrew/Cellar/libpq/16.1_1/ in the $PATH variable while running pip3 install psycopg2

I tried using DYLD_LIBRARY_PATH but that also didn’t work. I was not really in the mood to mess with setup.py and distutils since those were probably behind the generation of the actual compilation and linking commands. When I saw in the error above that Clang was using its -L flag on the libpq directory to gain access to the library files. And it was also looking for libssl and libcrypto as seen with the -lssl and -lcrypto flags. I theorized that if I just symlinked (or simply just temporarily copied) the libssl and libcrypto libraries to the folder it would find those there because of the flags being passed to it.

So I did exactly that. To test it out, I even built everything from source. In the end I just copied the libcrypto* and libssl* files to /opt/homebrew/Cellar/libpq/16.1_1/lib folder, assuming it would look up from the path where it found pg_config and look for a lib folder in pg_config’s upper directory.

And it worked.

Then went back to the libpq lib folder and deleted those files that I had just copied.

NOTE: This is obviously not the most ideal solution and I did this just for fun. It will work but it could mess up or break something else for you (example: programs/packages that depend on a specific version of OpenSSL, etc) so try it at your own risk. And make sure to remove whatever you put into the libpq lib folder

Shell Script

#!/bin/bash
libraries=(ssl crypto)
for l in ${libraries[@]}; do
	echo copying $i; 
	for i in $(find /opt/homebrew/opt/openssl\@3/lib -name "lib${l}*"); do
		echo cp -v $i /opt/homebrew/opt/libpq/lib/;
		cp -v $i /opt/homebrew/opt/libpq/lib/;
	done; 
done

echo "[press any key to delete when build is done]"
read

for i in ${libraries[@]}; do
	echo removing /opt/homebrew/opt/libpq/lib/lib$i*
	rm -vf /opt/homebrew/opt/libpq/lib/lib$i*
done

Making a simple C++/Win32 GUI application with MinGW – Part 2: Learning the basics

Making some simple programs is a good way of getting used to the Win32 API. Here’s the code for a basic application that shows a simple message box.

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

                   LPSTR lpCmdLine, int nCmdShow)

{

    LPCWSTR myText = L"Text for the message box";

    LPCWSTR myCaption = L"Caption for the message box";

    MessageBoxW(NULL, myText, myCaption, MB_OKCANCEL);

    return 0;

}

Basic Win32 program for creating a message box
Basic Win32 program for creating a message box

I’ll compile it with mingw-w64’s g++ that we setup in my previous post.

Compiling and running the message box program
Compiling and running the message box program

ws.exe in Explorer
ws.exe in Explorer

All of this might be confusing for people new to the Windows API, so let’s break it down line by line.

 #include <windows.h>

This line tells the g++ compiler to include the “windows.h” header file. Windows.h contains Windows API functions, macros and data types that must be used inside a Win32 application.

 

int WINAPI WinMain

This is the entry point for a graphical Windows application. In simple terms, it’s the equivalent of the standard C++ int main() but specific to Windows GUI applications.

(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

lpCmdLine contains the command line arguments as a long pointer. nCmdShow decides if the application window will be maximized, minimized or act normally on launch. hPrevInstance is not used these days, its value is NULL or 0. hInstance is a HANDLE to an instance, used to identify the executable when it is loaded into memory. (More info here)

LPCWSTR myText = L"Text for the message box";
LPCWSTR myCaption = L"Caption for the message box";

LPCWSTR is a typedef/alias for const wchar_t * data type. The L prefix before the double quote is used to define a wide character string literal as opposed to a normal string. For more information on Windows data types, look here.

MessageBoxW(NULL, myText, myCaption, MB_OKCANCEL);

MessageBoxW is a Win32 API function used to create a modal dialog box.

int MessageBoxW(
HWND hWnd,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType
);

hWnd is a handle to the owner window of the dialog. Since we don’t have a parent window for our message box, we’ll leave it as NULL.

uType decides the contents and behavior of the dialog box. It can be defined with flags explained here.

Here’s a picture of message boxes with different uType values.

Message Boxes with different uTypes
Message Boxes with different uType values

We can create a composite message box by combining uType flags using the bitwise OR (|) operator. For example,

MessageBoxW(NULL, myText, myCaption, MB_HELP | MB_OKCANCEL);

Message Box with multiple flags
Message Box with multiple flags

Making a simple C++/Win32 GUI application with MinGW – Part 1: Setting up the environment

I’ve always been fascinated by classic Win32 applications. They start up really quick, are always really fast and they rarely hog resources. The speed and fast startup is a huge plus for me, especially compared to “modern” desktop applications built with .NET.

I’m going to try and make a simple Win32 app, a program which helps me store the Spotlight lock-screen images that are changed periodically.

Spotlight Lockscreen (Source: Superuser.com)
Spotlight Lockscreen (Source: Superuser.com)

The Compiler

The first step is getting the tools we need. I don’t feel like installing the massive Visual Studio IDE for this project so I’ll go with mingw-w64 which is a free port of the GNU C/C++ Compiler and other libraries/tools for 64 bit Windows. To install this, I’ll use a package distribution program called WinBuilds.

WinBuilds
WinBuilds

All packages from WinBuilds total are around 500MB in size (unextracted), compared to the multiple gigabytes for Visual Studio.

winbuilds dir
winbuilds directory

The WinBuilds directory will contain a “bin” subdirectory, containing EXE files for all the tools. Ideally one should add this directory to the PATH environment variable, but I’m going to be using a batch script to manually set for a terminal session.

add-mingw-to-path.bat

set PATH=%PATH%;c:\winbuilds\bin\

where C:\winbuilds\bin is your WinBuilds install directory.

add MinGW to path
add MinGW to path

I’ll be using VSCode as my text editor for this series. First I’ll make a simple C++ program that prints “Hello” and compile it with g++. Then I run the output EXE file. Seems to work so far.

Compiling and running my Hello.cpp file
Compiling and running my Hello.cpp file

Mingw-w64’s g++ produces Windows PE (portable executable) .EXE files, which is neat. I’ve not used any Windows APIs here, so hello.exe is not really a proper Win32 application yet.

To use the Windows API, we need to include windows.h and use Windows API functions. To test my setup I’ll use the first program from theForger’s Win32 API Programming Tutorial, the most famous Win32 API programming tutorial.

Hello.exe GUI window appears
Hello.exe GUI window appears

It works. I’ll add more stuff to it in the next part.